/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bungabungaball.gamestates;

import bungabungaball.GlobalSettings;
import bungabungaball.PlayerControl;
import bungabungaball.gamestates.menu.Menu;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;

import bungabungaball.gamestates.menu.MenuEntry;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.esotericsoftware.kryonet.Server;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.newdawn.slick.Image;

/**
 * Start a network game.
 *
 * @author Ingo Klose, Stephan Meyer, Sebastian Lehmann
 * @version 1.0
 */
public class StartNetworkGame extends BasicGameState implements Menu {

    /**
     * the id of the game state
     */
    private int stateID = -1;
    /**
     * Is the server correnctly created
     */
    private boolean serverCorrectlyCreated;
    /**
     * *
     * The time when the game state is opened
     */
    private long currentTimeOpen;
    /**
     * Is a cliend connected to the server
     */
    private boolean clientConnectedToServer;
    /*
     * a menu entry to finally start the game
     */
    private MenuEntry startGame;
    /**
     * has the player clicked to start
     */
    private boolean startGameOkForServer;
    /**
     * has the client sent to start
     */
    private boolean startGameOkForClient;
    /**
     * An image of the driver
     */
    private Image driver;
    /**
     * An image of the driver
     */
    private Image driver2;
    /**
     * Bunga Logo
     */
    private Image bunga;
    /**
     * Bunga Logo
     */
    private Image bungamenu;
    /**
     * x Position of the driver
     */
    private double driverX;
    /**
     * Y Position of the driver
     */
    private double driverY;
    /**
     * A counter for the driver
     */
    private double counter = 0;
    /**
     * A checker for the driver
     */
    private boolean checker = true;

    /**
     * Constructor
     *
     * @param stateID
     */
    public StartNetworkGame(int stateID) {
        this.stateID = stateID;
        serverCorrectlyCreated = false;
        driverX = 600;
        driverY = 350;
    }

    /**
     * get the ID of the state
     *
     * @return id of the state
     */
    @Override
    public int getID() {
        return stateID;
    }

    /**
     * Init server, menu
     *
     * @param gc
     * @param sbg
     * @throws SlickException
     */
    @Override
    public void init(GameContainer gc, StateBasedGame sbg) throws SlickException {
        startGame = new MenuEntry("Spiel starten", 100, 500, gc.getDefaultFont());

        if (PlayerControl.server != null) {
            PlayerControl.server.stop();
            PlayerControl.server.close();
            PlayerControl.server = null;
        }
        PlayerControl.server = new Server(10000, 10000);
        PlayerControl.server.start();
        try {
            PlayerControl.server.bind(54555, 54777);
            Kryo kryo = PlayerControl.server.getKryo();

            for (Class cl : GlobalSettings.kryoRegisterClassNames) {
                kryo.register(cl);
            }

            PlayerControl.server.addListener(new Listener() {
                @Override
                public void received(Connection connection, Object object) {
                    if (object instanceof Boolean) {
                        Boolean request = (Boolean) object;

                        if (request) {
                            startGameOkForClient = true;
                            PlayerControl.server.removeListener(this);
                        }
                    }
                }
            });

            serverCorrectlyCreated = true;
        } catch (IOException ex) {
            Logger.getLogger(StartNetworkGame.class.getName()).log(Level.SEVERE, null, ex);
            System.out.println("Der Server konnte nicht erstellt werden!");
            serverCorrectlyCreated = false;
        }
        driver = new Image("\\img\\player1.png");

        driver2 = new Image("\\img\\player2.png");
        driver2.setRotation(45);

        bunga = new Image("\\img\\bungabunga.png");
    }

    /**
     * reset everything
     *
     * @param gc
     * @param sbg
     * @throws SlickException
     */
    @Override
    public void enter(GameContainer gc, StateBasedGame sbg) throws SlickException {
        currentTimeOpen = gc.getTime();
        clientConnectedToServer = false;
        startGameOkForServer = false;
        startGameOkForClient = false;
    }

    /**
     * render the menu
     *
     * @param gc
     * @param sbg
     * @param g
     * @throws SlickException
     */
    @Override
    public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException {
        long time = gc.getTime() - currentTimeOpen;
        int numberOfDots = (int) (time / 1000) % 3 + 1;
        Input input = gc.getInput();
        String dots = "";
        for (int i = 0; i < numberOfDots; i++) {
            dots += ".";
        }
        g.setColor(Color.white);
        if (serverCorrectlyCreated) {
            g.drawString("Der Server wurde erstellt. Warte auf Verbindungen" + dots, 100, 100);
            if (clientConnectedToServer) {
                g.drawString("Verbindung hergestellt", 100, 120);


                g.drawString("Selber bereit: " + (startGameOkForServer ? "Ja" : "Nein"), 100, 150);
                g.drawString("Gegner bereit: " + (startGameOkForClient ? "Ja" : "Nein"), 100, 170);

                int mouseX = input.getAbsoluteMouseX();
                int mouseY = input.getAbsoluteMouseY();

                g.setColor(startGame.checkMouseIn(mouseX, mouseY) ? Color.green : Color.white);
                g.drawString(startGame.text, startGame.x, startGame.y);
            }
        } else {
            g.drawString("Der Server konnte nicht erstellt werden!", 100, 100);
        }
        gc.getTime();

        g.drawImage(driver, (int) driverX, (int) driverY);

        g.drawImage(driver2, 200, 200);


        g.drawImage(bunga, 400, 0);
    }

    /**
     * handle all input
     *
     * @param gc
     * @param sbg
     * @param delta
     * @throws SlickException
     */
    @Override
    public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException {
        // Handle the Input
        Input input = gc.getInput();

        int mouseX = input.getAbsoluteMouseX();
        int mouseY = input.getAbsoluteMouseY();

        if (input.isKeyDown(Input.KEY_ESCAPE)) {
            try {
                Thread.sleep(250);
            } catch (InterruptedException ex) {
                Logger.getLogger(GamePlay.class.getName()).log(Level.SEVERE, null, ex);
            }
            sbg.enterState(bungabungaball.BungaBungaBall.MAINMENUSTATE);
        }
        if (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON)) {
            if (startGame.checkMouseIn(mouseX, mouseY)) {
                PlayerControl.server.sendToAllTCP(new Boolean(true));
                startGameOkForServer = true;
            }
        }

        // Check number of connections:
        if (PlayerControl.server.getConnections().length > 0) {
            clientConnectedToServer = true;
        }

        // Check if start Game:
        if (startGameOkForServer && startGameOkForClient) {
            GlobalSettings.currentGameMode = GlobalSettings.gameModes.Server;
            sbg.enterState(bungabungaball.BungaBungaBall.GAMEPLAYSTATESingle);
        }

        this.drive();
        this.drive();
    }

    /**
     * Updates the driver Image
     */
    public void drive() {
        //x = 600 y = 400
        double speedRotation = Math.toRadians(driver.getRotation() - 90.f);

        driverX = driverX + 2 * Math.cos(speedRotation);
        driverY = driverY + 2 * Math.sin(speedRotation);

        if (checker && counter <= 270) {
            driver.rotate(1);
        } else if (!checker && counter <= 270) {
            driver.rotate(-1);
        }
        counter++;
        if (counter == 385) {
            counter = 0;
            if (checker) {
                checker = false;
            } else {
                checker = true;
            }
        }
    }
}
